﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;

namespace MockupDesigner.AppItems.Commands
{
    public class ToBackFrontCommand : ICommand
    {

        public CommandType CommandType
        {
            get { return CommandType.Undoable; }
        }

        private DesignerCanvas designerCanvas;
        private OppositeType oppositeType;

        private IList<UIElement> selectionSorted = new List<UIElement>();
        private IList<UIElement> childrenSorted = new List<UIElement>();
        private Dictionary<UIElement, int> elementsChanged = new Dictionary<UIElement, int>();



        public void Undo()
        {
            foreach (UIElement item in elementsChanged.Keys)
            {
                Canvas.SetZIndex(item, elementsChanged[item]);
            }
        }

        public void Execute(object target, params object[] parameters)
        {
            if (!(target is DesignerCanvas))
            {
                throw new InvalidCastException("The target must be a DesignerCanvas");
            }
            this.designerCanvas = (DesignerCanvas)target;

            if (parameters[0] is string)
            {
                this.oppositeType = (OppositeType) new EnumConverter(typeof(OppositeType)).ConvertFrom(parameters[0]);
            }
            else if (parameters[0] is OppositeType)
            {
                this.oppositeType = (OppositeType)parameters[0];
            }
            else
            {
                throw new InvalidCastException("The target must be a OppositeType");
            }
            
            Redo();
        }

        public void Redo()
        {
            if (selectionSorted.Count == 0)
            {
                selectionSorted = (from item in this.designerCanvas.SelectionService.CurrentSelection
                                   orderby Canvas.GetZIndex(item as UIElement) ascending
                                   select item as UIElement).ToList();
            }
            if (childrenSorted.Count == 0)
            {
                childrenSorted = (from UIElement item in this.designerCanvas.Children
                                  orderby Canvas.GetZIndex(item as UIElement) ascending
                                  select item as UIElement).ToList();
            }
            if (elementsChanged.Count == 0)
            {
                foreach (UIElement child in childrenSorted)
                {
                    elementsChanged.Add(child, Canvas.GetZIndex(child));
                }
            }
            int i = 0;
            int j = 0;
            foreach (UIElement item in childrenSorted)
            {
                if (selectionSorted.Contains(item))
                {
                    int idx = Canvas.GetZIndex(item);
                    if (this.oppositeType == OppositeType.ToFront)
                        Canvas.SetZIndex(item, childrenSorted.Count - selectionSorted.Count + j++);
                    else
                        Canvas.SetZIndex(item, j++);
                }
                else
                {
                    if (this.oppositeType == OppositeType.ToFront)
                        Canvas.SetZIndex(item, i++);
                    else
                        Canvas.SetZIndex(item, selectionSorted.Count + i++);
                }
            }
        }
    }

    public enum OppositeType
    {
        ToBack,
        ToFront
    }
}
